Na aula passada, vimos que os domicílios são a unidade amostral, enquando as unidades de consumo (UC) são a unidade básica de pesquisa. Em linhas gerais, isso significa que a seleção de pessoas entrevistadas pela POF se dá pela seleção dos domicílio, no procedimento descrito anteriormente. E que as informações da pesquisa são agregadas, no nível mais básico, por unidades de consumo. Ou seja, ao contrário da PNAD Contínua Anual, na qual a renda per capita (por exemplo) significa a renda média dos moradores de um mesmo domicílio, na POF ela significa a renda média dos membros da unidade de consumo.
Um domicílio contém ao menos uma unidade de consumo, e toda unidade de consumo pertence a um e apenas um domicílio. Analogamente, uma unidade de consumo contém ao menos uma pessoa, e toda pessoa pertence a uma e apenas uma unidade de consumo.
Nessa discussão, dois registros são centrais. O primeiro é DOMICÍLIO, que contém dados sobre todos os domicílios da amostra, como água corrente, coleta de lixo e energia elétrica. Nesse registro, cada linha é um domicílio (o total de linhas é o total de domicílios na amostra da POF). O segundo é MORADOR, que contém dados de todas as pessoas da amostra, como idade, anos de estudo e se lancha na creche. Nesse registro, cada linha é uma pessoa, e o total de linhas é o total de pessoas na amostra da POF. Não há um registro “unidades de consumo”.
Assim, precisamos criar indicadores que permitam identificar os domicílios, unidades de consumo e pessoas entre os diferentes registros da POF (no último caso, nem sempre será possível).
Primeiro, vamos carregar os dois registros da POF
library(tidyverse)
pof_domicilio <- read_rds("./dados/pof_domicilio.rds")
pof_morador <- read_rds("./dados/pof_morador.rds")
Como a pof_domicilio tem o domicílio como maior nível de desagregação, só poderemos criar um identificador de domicílio (id_dom). Basicamente o id_dom é composto pelo identificador da UPA e pelo número do domicílio naquela UPA.
A função str_c agrupa conjuntos de caracteres. É
semelhante ao CONCATENAR do Excel. A função
n_distinct retorna o número de valores distintos da
variável e n retorna o número de elementos (no caso de um
df, o número de linhas)
pof_domicilio <- pof_domicilio %>%
mutate(id_dom = str_c(COD_UPA, NUM_DOM))
pof_domicilio %>%
summarise(numero_domicilios = n_distinct(id_dom),
numero_linhas = n())
## # A tibble: 1 × 2
## numero_domicilios numero_linhas
## <int> <int>
## 1 57920 57920
Como podemos ver, os números são iguais.
Agora na pof_morador, podemos criar identificadores de domicílio (id_dom), de unidade de consumo (id_uc) e de pessoas (id_pes).
pof_morador <- pof_morador %>%
mutate(id_dom = str_c(COD_UPA, NUM_DOM),
id_uc = str_c(COD_UPA, NUM_DOM, NUM_UC),
id_pes = str_c(COD_UPA, NUM_DOM, NUM_UC, COD_INFORMANTE))
pof_morador %>%
summarise(numero_domicilios = n_distinct(id_dom),
numero_uc = n_distinct(id_uc),
numero_pessoas = n_distinct(id_pes),
numero_linhas = n())
## # A tibble: 1 × 4
## numero_domicilios numero_uc numero_pessoas numero_linhas
## <int> <int> <int> <int>
## 1 57920 58039 178419 178431
O número de domicílios é o mesmo do registro pof_domicílios - está correto. Mas o número de pessoas não está igual ao número de linhas. Qual foi o erro? O erro é um problema no tamanho das variáveis NUM_DOM, NUM_UC e COD_INFORMANTE.
pof_morador %>%
group_by(id_pes) %>%
mutate(x = n()) %>%
ungroup() %>%
filter(x > 1) %>%
select(COD_UPA, NUM_DOM, NUM_UC, COD_INFORMANTE, id_pes) %>%
arrange(id_pes)
## # A tibble: 24 × 5
## COD_UPA NUM_DOM NUM_UC COD_INFORMANTE id_pes
## <chr> <chr> <chr> <chr> <chr>
## 1 120005467 1 1 11 1200054671111
## 2 120005467 11 1 1 1200054671111
## 3 130017335 1 1 11 1300173351111
## 4 130017335 11 1 1 1300173351111
## 5 130017335 1 1 12 1300173351112
## 6 130017335 11 1 2 1300173351112
## 7 130017335 1 1 13 1300173351113
## 8 130017335 11 1 3 1300173351113
...
Pegando as primeiras duas linhas como exemplo, vemos que o erro é
causado pela combinação do mesmo valor para COD_UPA e
NUM_UC com, em um caso NUM_DOM == 11 e
COD_INFORMANTE == 1 e, no outro, NUM_DOM == 1
e COD_INFORMANTE == 11, gerando assim o mesmo
id_pes para duas pessoas diferentes.
Para resolver isso, basta termos todos os valores de NUM_DOM, NUM_UC e COD_INFORMANTE com dois dígitos (01 ao invés de 1). Lembrando que precisamos dessa alteração em todos os registros da POF, pois esses indicadores são nossas chaves para agregar as diferentes tabelas.
Fazemos então
pof_domicilio <- pof_domicilio %>%
mutate(NUM_DOM = str_pad(NUM_DOM, 2, "left", "0"),
id_dom = str_c(COD_UPA, NUM_DOM))
pof_morador <- pof_morador %>%
mutate(NUM_DOM = str_pad(NUM_DOM, 2, "left", "0"),
NUM_UC = str_pad(NUM_UC, 2, "left", "0"),
COD_INFORMANTE = str_pad(COD_INFORMANTE, 2, "left", "0"),
id_dom = str_c(COD_UPA, NUM_DOM),
id_uc = str_c(COD_UPA, NUM_DOM, NUM_UC),
id_pes = str_c(COD_UPA, NUM_DOM, NUM_UC, COD_INFORMANTE))
pof_domicilio %>%
summarise(numero_domicilios = n_distinct(id_dom),
numero_linhas = n())
## # A tibble: 1 × 2
## numero_domicilios numero_linhas
## <int> <int>
## 1 57920 57920
pof_morador %>%
summarise(numero_domicilios = n_distinct(id_dom),
numero_uc = n_distinct(id_uc),
numero_pessoas = n_distinct(id_pes),
numero_linhas = n())
## # A tibble: 1 × 4
## numero_domicilios numero_uc numero_pessoas numero_linhas
## <int> <int> <int> <int>
## 1 57920 58039 178431 178431
Problema resolvido. De fato, é tedioso fazer isso toda vez que for ler a POF. No entanto, é importante mostrar pequenos erros que podem ter efeitos negativos na nossa análise.
Para termos certeza de que estamos usando o número certo de unidades de consumo e de pessoas, podemos tentar replicar algumas tabelas do SIDRA. Como exemplo, vamos fazer o total de famílias e o tamanho médio de famílias para o Brasil e para a Paraíba. A tabela de referência no SIDRA é a 6977 e pode ser acessada clicando aqui.
pof_morador %>%
group_by(id_uc) %>%
mutate(n_uc = n(),
PESO_FINAL = as.numeric(PESO_FINAL)) %>%
ungroup() %>%
filter(V0306 == "1") %>%
summarise(total_uc = sum(PESO_FINAL),
tamanho_medio = round(sum(n_uc*PESO_FINAL)/sum(PESO_FINAL),2))
## # A tibble: 1 × 2
## total_uc tamanho_medio
## <dbl> <dbl>
## 1 69017704. 3
pof_morador %>%
filter(UF == "25") %>%
group_by(id_uc) %>%
mutate(n_uc = n(),
PESO_FINAL = as.numeric(PESO_FINAL)) %>%
ungroup() %>%
filter(V0306 == "1") %>%
summarise(total_uc = sum(PESO_FINAL),
tamanho_medio = round(sum(n_uc*PESO_FINAL)/sum(PESO_FINAL),2))
## # A tibble: 1 × 2
## total_uc tamanho_medio
## <dbl> <dbl>
## 1 1265385. 3.13
Antes de falar sobre como calcular as despesas, vale demonstrar a
integração entre os diferentes registros. Para analisarmos o valor e
composição de despesas de diferentes grupos populacionais, precisamos de
informações de pessoas, famílias e domicílios. Assim, é preciso integrar
as informações de despesa, que estão nos registros Aluguel
estimado, Caderneta coletiva, Despesa coletiva,
Despesa individual, Rendimento do trabalho e
Outros rendimentos aos registros Morador e
Domicílio. Isso é feito por meio das variáveis indicadoras
id_dom e id_uc. Vamos usar como exemplo os
registros Morador e Aluguel estimado.
pof_aluguel_estimado <- read_rds("./dados/pof_aluguel_estimado.rds") %>%
mutate(NUM_DOM = str_pad(NUM_DOM, 2, "left", "0"),
NUM_UC = str_pad(NUM_UC, 2, "left", "0"),
id_dom = str_c(COD_UPA, NUM_DOM),
id_uc = str_c(COD_UPA, NUM_DOM, NUM_UC))
pof_join <- pof_morador %>%
left_join(pof_aluguel_estimado, by = "id_uc")
Percebam que, aqui, eu usei o left_join, com
pof_morador no primeiro argumento. Isso vem porque queremos
preservar todas as linhas dessa tabela, para podermos separar os gastos
por características das pessoas e das famílias.
Para começar a olhar as despesas, temos três arquivos centrais:
indice <- readxl::read_xls("./memoria_de_calculo/Indice_Despesa.xls")
tradutor <- readxl::read_xls("./tradutores/Tradutor_Despesa_Geral.xls")
cadastro <- readxl::read_xls("./documentacao/Cadastro de Produtos.xls",
col_types = "text")
A tabela indice apenas relaciona o nível de desagregação da despesa com sua respectiva descrição.
indice
## # A tibble: 93 × 3
## INDICE NIVEL DESCRICAO
## <dbl> <dbl> <chr>
## 1 1 0 DESPESA TOTAL
## 2 2 1 DESPESAS CORRENTES
## 3 3 11 DESPESAS DE CONSUMO
## 4 4 1101 ALIMENTACAO
## 5 5 1102 HABITACAO
## 6 6 110201 ALUGUEL
...
O cadastro de produtos, por sua vez, relaciona o código do produto com sua respectiva descrição e o quadro no qual o produto se encontra.
cadastro
## # A tibble: 13,474 × 3
## QUADRO `CÓDIGO DO PRODUTO` `DESCRIÇÃO DO PRODUTO`
## <chr> <chr> <chr>
## 1 0 000101 ALUGUEL ESTIMADO
## 2 6 600101 ENERGIA ELETRICA (KWH)
## 3 6 600201 AGUA E ESGOTO
## 4 6 600301 GAS ENCANADO
## 5 6 600401 TELEFONE FIXO
## 6 6 600501 ACESSO A INTERNET (DISCADA, BANDA LARGA, VIA SATE…
...
Por fim, a tabela mais importante para nós é a tradutor.
indice <- readxl::read_xls("./memoria_de_calculo/Indice_Despesa.xls") %>%
mutate(num_char = nchar(NIVEL),
cod_par = case_when(nchar(NIVEL) == 1 ~ "0",
nchar(NIVEL) == 2 ~ str_sub(NIVEL,1,-2),
nchar(NIVEL) == 4 ~ str_sub(NIVEL,1,-3),
nchar(NIVEL) == 6 ~ str_sub(NIVEL,1,-3),
nchar(NIVEL) == 7 ~ str_sub(NIVEL,1,-2)
),
NIVEL = as.numeric(NIVEL),
DESCRICAO = case_when(DESCRICAO == "OUTRAS" ~ str_c(DESCRICAO," ",NIVEL),
TRUE ~ DESCRICAO)) %>%
filter(is.na(cod_par) == F) %>%
mutate(x = match(cod_par, NIVEL),
desc_par = case_when(NIVEL == "0" ~ "",
TRUE ~ DESCRICAO[x]))
indice_geral <- indice %>%
filter(num_char <= 4)
indice_consumo <- indice %>%
filter(num_char >= 3 | (num_char == 2 & NIVEL == "11")) %>%
filter(cod_par != 12) %>%
mutate(desc_par = case_when(NIVEL == "11" ~ "",
TRUE ~ desc_par))
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
fig_geral <- plot_ly(
type="treemap",
labels=indice_geral$DESCRICAO %>% stringr::str_wrap(width = 15),
parents=indice_geral$desc_par %>% stringr::str_wrap(width = 15),
textposition = "middle center"
)
fig_consumo <- plot_ly(
type="treemap",
labels=indice_consumo$DESCRICAO %>% stringr::str_wrap(width = 15),
parents=indice_consumo$desc_par %>% stringr::str_wrap(width = 15),
textposition = "middle center"
)
fig_geral
fig_consumo